/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package asociacion;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import manejadorConsultas.ConsultasDatamart;
import rutas.GetRoutes;

/**
 *
 * @author JORGE
 */
public class ArmadorDataSet {
    private HashMap<Integer, Estudiante> estudiantes;
    private static String query="SELECT tabulado_dd, estudiante, programa_acad, sexo, estadocivil, estratosocioe, trabaja, codigo, nombre, creditos, nivel, tipoasignatura, generico, anual, habilitable, validable FROM( ( ( SELECT tabulado_dd, estudiante, demografia, sexo, estadocivil, estratosocioe, trabaja, asignatura FROM( ( SELECT tabulado_dd, estudiante, demografia, asignatura FROM cancelaciones ORDER BY estudiante ) as canc NATURAL JOIN ( SELECT demograficos_k as demografia, sexo, estadocivil, estratosocioe, trabaja FROM demograficos ) as demogs ) ) as sinasigs NATURAL JOIN ( SELECT asignatura_k as asignatura, codigo, nombre, creditos, nivel, tipoasignatura, generico, anual, habilitable, validable FROM asignatura ORDER BY codigo ) as asigns ) as sinEst NATURAL JOIN ( SELECT estudiante_k as estudiante, programa_acad FROM estudiante ) as conEst )ORDER BY codigo;";
    
    static void dbg(Object... o) {
        System.out.println(Arrays.deepToString(o));
    }
    
    public ArmadorDataSet(){
        ConsultasDatamart consultador= new ConsultasDatamart();
        ResultSet  rs= null;
        try
        {
            consultador.consultaGeneral(query);
            rs= consultador.getRs();
        }
        catch(SQLException excp)
        {
            System.err.println("No pude hacer la query");
            excp.printStackTrace();
        }
        estudiantes= new HashMap<Integer, Estudiante>();
        try{
            rs.next();
            int est=0;
            Estudiante estuTmp= new Estudiante();
            
            Asignatura asignTmp;
            do{
                asignTmp= null;
                asignTmp= new Asignatura();
                asignTmp.setAnual((Boolean) rs.getObject("anual"));
                asignTmp.setCodigo((String)rs.getObject("codigo"));
                asignTmp.setCreditos(Double.parseDouble(""+(Integer)rs.getObject("creditos")));
                asignTmp.setGenerico((Boolean)rs.getObject("generico"));
                asignTmp.setHabilitable((Boolean)rs.getObject("habilitable"));
                asignTmp.setNivel((String)rs.getObject("nivel"));
                asignTmp.setNombre((String)rs.getObject("nombre"));
                asignTmp.setTipo((String)rs.getObject("tipoasignatura"));
                asignTmp.setValidable((Boolean)rs.getObject("validable"));
                
                est=(Integer)rs.getObject(2);
                if(estudiantes.containsKey(est)){
                    estuTmp=estudiantes.get(est);     
                } else{
                    estuTmp= new Estudiante();
                    estuTmp.addDemog((String)rs.getObject("programa_acad"));
                    estuTmp.addDemog((String)rs.getObject("sexo"));
                    estuTmp.addDemog((String)rs.getObject("estadocivil"));
                    estuTmp.addDemog(""+(Integer)rs.getObject("estratosocioe"));
                    {
                        String trabaja="No_Trabaja";
                        if((Boolean)rs.getObject("trabaja"))trabaja="Trabaja";
                        estuTmp.addDemog(trabaja);
                    }
                                    
                }
                
                estuTmp.addAsignatura(asignTmp);
                estudiantes.put(est, estuTmp);
               // Se crea un array que será una de las filas de la tabla.
                
//               cont++;
               // Se rellena cada posición del array con una de las columnas de la tabla en base de datos.
//               for (int i=0;i<colNames.length;i++)
//                  fila[i] = rs.getObject(i+1); // El primer indice en rs es el 1, no el cero, por eso se suma 1.
//               fila[0]=rs.getObject(1);
//               fila[1]=rs.getObject(2);
               // Se añade al modelo la fila completa.
//               System.out.println("ResultSet Convertido!!");
                

            }while (rs.next());
            
            
            rs.beforeFirst();
        }catch(SQLException excp) {
            System.err.println("No fue posible recoger los datos");
            excp.printStackTrace();
        }
//        Debug
//        for (Iterator<Estudiante> it = estudiantes.iterator(); it.hasNext();) {
//            Estudiante estudiante = it.next();
//            dbg(estudiante);
//        }
    }
    
    public void escribirCSV() throws IOException{
        String salida=GetRoutes.escogerRutaArchivoGuardar();
        PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(salida)));
        for (Map.Entry<Integer, Estudiante> entry : estudiantes.entrySet()) {
            Estudiante estudiante = entry.getValue();
            String demogs="";
            String cursos="";
            ArrayList datos= estudiante.getDemogs();
            for (Iterator<Object> it1 = datos.iterator(); it1.hasNext();) {
                String datodemog = (String)it1.next();
                if(!(demogs.equals(""))) demogs+=",";
                demogs+=datodemog;
            }
            datos=estudiante.getAsignaturas();
            Collections.sort(datos, new ComparadorAsignaturas());
            for (Iterator<Object> it1 = datos.iterator(); it1.hasNext();) {
                Asignatura datoAsign = (Asignatura)it1.next();
                if(!(cursos.equals(""))) cursos+=",";
                cursos+=datoAsign.getCodigo();
            }
            System.out.printf("%s, %s\n", demogs, cursos);
            output.printf("%s,%s\n", demogs, cursos);
        }
        output.close();
    }
    
    public static void main (String [] args){
        ArmadorDataSet obj= new ArmadorDataSet();
        try{
            obj.escribirCSV();
        }catch(IOException excp)
        {
            System.err.println("No pude escribir a la salida");
            excp.printStackTrace();
        }
    }
    
}


class Estudiante{
    ArrayList<String> demos;
    HashMap<String, Asignatura> asignatura;
    public Estudiante(){
        asignatura= new HashMap<String, Asignatura>();
        demos= new ArrayList<String>();
    }
    public Estudiante(String [] arr_cursos, String [] arr_demogs){
        asignatura= new HashMap<String, Asignatura>();
        demos= new ArrayList<String>();
    }
    public ArrayList<Asignatura> getAsignaturas(){
        ArrayList<Asignatura> asigns=new ArrayList<Asignatura>();
        for (Map.Entry<String, Asignatura> entry : asignatura.entrySet()) {
            String string = entry.getKey();
            Asignatura asignatura1 = entry.getValue();
            asigns.add(asignatura1);
        }
        return asigns;
    }
    public ArrayList<String> getDemogs(){
       return this.demos;    
    }
    public void addAsignatura(Asignatura asign){
        if(this.asignatura.containsKey(asign.codigo)){
//            System.err.println("Ya esta la asignatura");
        }else
        {
            this.asignatura.put(asign.codigo, asign);
        }
    }
    public void setDemogs(ArrayList<String> demogs){
        this.demos= new ArrayList<String>(demogs);
    }
    
    public void addDemog(String datoDemog){
        this.demos.add(datoDemog);
    }

    @Override
    public String toString() {
        return "Estudiante{" + "demos=" + Arrays.deepToString(demos.toArray()) + ", asignatura=" + Arrays.deepToString(asignatura.values().toArray()) + '}';
    }
}

class ComparadorAsignaturas implements Comparator{
   
    public int compare(Object emp1, Object emp2){
   
        /*
         * parameter are of type Object, so we have to downcast it
         * to Employee objects
         */
       
        String asign1cod = ((Asignatura)emp1).getCodigo();        
        String asign2cod = ((Asignatura)emp2).getCodigo();
        return asign1cod.compareTo(asign2cod);    
    }
   
}

class Asignatura{
    String codigo;
    String nombre;
    Double creditos;
    String nivel;
    String tipo;
    boolean generico, anual, habilitable, validable;
    
    public Asignatura(String cod, String nom, Double cred, String lvl, String tipo,
            boolean generico, boolean anual, boolean habilitable, boolean validable){
        this.codigo=cod;
        this.nombre=nom;
        this.creditos=cred;
        this.nivel=lvl;
        this.tipo=tipo;
        this.generico=generico;
        this.anual=anual;
        this.habilitable=habilitable;
        this.validable=validable;
    
    }
    public Asignatura(){
        this.codigo="";
        this.nombre="";
        this.creditos=0.0;
        this.nivel="";
        this.tipo="";
        this.generico=false;
        this.anual=false;
        this.habilitable=false;
        this.validable=false;
    }

    public boolean equals(Asignatura obj) {
        boolean comparacion=this.codigo==obj.codigo;
        return comparacion;
    }

    public boolean isAnual() {
        return anual;
    }

    public String getCodigo() {
        return codigo;
    }

    public Double getCreditos() {
        return creditos;
    }

    public boolean isGenerico() {
        return generico;
    }

    public boolean isHabilitable() {
        return habilitable;
    }

    public String getNivel() {
        return nivel;
    }

    public String getNombre() {
        return nombre;
    }

    public String getTipo() {
        return tipo;
    }

    public boolean isValidable() {
        return validable;
    }
//    SETTERS

    public void setAnual(boolean anual) {
        this.anual = anual;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public void setCreditos(Double creditos) {
        this.creditos = creditos;
    }

    public void setGenerico(boolean generico) {
        this.generico = generico;
    }

    public void setHabilitable(boolean habilitable) {
        this.habilitable = habilitable;
    }

    public void setNivel(String nivel) {
        this.nivel = nivel;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    public void setValidable(boolean validable) {
        this.validable = validable;
    }

    @Override
    public String toString() {
        return "Asignatura{" + "codigo=" + codigo + '}';
    }
    
    
}
